package main

import (
    "encoding/json"
    "fmt"
    "log"

    "go.etcd.io/bbolt"
)

// 定义 JSON 数据的结构
type Params struct {
    Min            string `json:"min"`
    Max            string `json:"max"`
    MinMaxAlarm    bool   `json:"minMaxAlarm"`
    Step           string `json:"step"`
    StepAlarm      bool   `json:"stepAlarm"`
    DataLength     string `json:"dataLength"`
    DataLengthAlarm bool  `json:"dataLengthAlarm"`
    StartTime      int    `json:"startTime"`
    Duration       int    `json:"duration"`
}

type Property struct {
    Index      int    `json:"index"`
    Name       string `json:"name"`
    UploadName string `json:"uploadName"`
    Label      string `json:"label"`
    Type       int    `json:"type"`
    Decimals   int    `json:"decimals"`
    Unit       string `json:"unit"`
    Params     Params `json:"params"`
}

type DeviceModel struct {
    Name       string              `json:"name"`
    Label      string              `json:"label"`
    Code       string              `json:"code"`
    Properties map[string]Property `json:"properties"`
}

// 数据库文件路径
const dbPath = "openGW_bbolt.db"

// 打开或创建数据库
func openDB() (*bbolt.DB, error) {
    return bbolt.Open(dbPath, 0755, nil)
}

// 添加或更新模型
func saveModel(db *bbolt.DB, modelName string, modelData DeviceModel) error {
    return db.Update(func(tx *bbolt.Tx) error {
        // 获取或创建 models bucket
        bucket, err := tx.CreateBucketIfNotExists([]byte("models"))
        if err != nil {
            return err
        }

        // 将模型数据转换为 JSON
        data, err := json.Marshal(modelData)
        if err != nil {
            return err
        }

        // 以 modelName 作为键存储数据
        return bucket.Put([]byte(modelName), data)
    })
}

// 根据模型名称查询模型数据
func getModel(db *bbolt.DB, modelName string) (DeviceModel, error) {
    var model DeviceModel

    err := db.View(func(tx *bbolt.Tx) error {
        bucket := tx.Bucket([]byte("models"))
        if bucket == nil {
            return fmt.Errorf("bucket 'models' 不存在")
        }

        // 获取模型数据
        data := bucket.Get([]byte(modelName))
        if data == nil {
            return fmt.Errorf("模型 '%s' 不存在", modelName)
        }

        // 解析 JSON 数据
        return json.Unmarshal(data, &model)
    })

    return model, err
}

// 删除指定模型
func deleteModel(db *bbolt.DB, modelName string) error {
    return db.Update(func(tx *bbolt.Tx) error {
        bucket := tx.Bucket([]byte("models"))
        if bucket == nil {
            return fmt.Errorf("bucket 'models' 不存在")
        }

        return bucket.Delete([]byte(modelName))
    })
}

// 查询所有模型
func listAllModels(db *bbolt.DB) ([]DeviceModel, error) {
    var models []DeviceModel

    err := db.View(func(tx *bbolt.Tx) error {
        bucket := tx.Bucket([]byte("models"))
        if bucket == nil {
            return fmt.Errorf("bucket 'models' 不存在")
        }

        return bucket.ForEach(func(k, v []byte) error {
            var model DeviceModel
            if err := json.Unmarshal(v, &model); err != nil {
                return err
            }
            models = append(models, model)
            return nil
        })
    })

    return models, err
}


// 更新指定模型中的属性
func updateProperty(db *bbolt.DB, modelName, propertyName string, updatedProperty Property) error {
  return db.Update(func(tx *bbolt.Tx) error {
      bucket := tx.Bucket([]byte("models"))
      if bucket == nil {
          return fmt.Errorf("bucket 'models' 不存在")
      }

      data := bucket.Get([]byte(modelName))
      if data == nil {
          return fmt.Errorf("模型 '%s' 不存在", modelName)
      }

      // 将 JSON 数据解析为 DeviceModel 结构
      var model DeviceModel
      if err := json.Unmarshal(data, &model); err != nil {
          return err
      }

      // 更新模型中的属性
      model.Properties[propertyName] = updatedProperty

      // 将更新后的模型重新序列化为 JSON 并存储
      updatedData, err := json.Marshal(model)
      if err != nil {
          return err
      }

      return bucket.Put([]byte(modelName), updatedData)
  })
}

// 示例调用和测试
func Update(db *bbolt.DB) {

  // 假设模型已经存在，尝试更新其属性
  updatedProperty := Property{
      Index:      0,
      Name:       "Inp1",
      UploadName: "Inp1",
      Label:      "第1路脉冲常数更新",
      Type:       2,
      Decimals:   2,
      Unit:       "更新后的单位",
      Params: Params{
          Min:            "10",
          Max:            "100",
          MinMaxAlarm:    true,
          Step:           "1",
          StepAlarm:      true,
          DataLength:     "4",
          DataLengthAlarm: false,
          StartTime:      0,
          Duration:       0,
      },
  }

  // 更新模型的属性
  modelName := "电表模型"
  propertyName := "Inp1"
  if err := updateProperty(db, modelName, propertyName, updatedProperty); err != nil {
      log.Fatalf("更新模型属性失败: %v", err)
  }
  fmt.Printf("模型 '%s' 的属性 '%s' 已更新\n", modelName, propertyName)

  // 验证更新结果
  model, err := getModel(db, modelName)
  if err != nil {
      log.Fatalf("查询模型失败: %v", err)
  }
  fmt.Printf("查询到更新后的模型: %+v\n", model)
}



func main() {
    db, err := openDB()
    if err != nil {
        log.Fatalf("打开数据库失败: %v", err)
    }
    defer db.Close()

    // 创建一个示例模型数据
    exampleModel := DeviceModel{
        Name:  "电表模型",
        Label: "DTL",
        Code:  "10001006",
        Properties: map[string]Property{
            "Inp1": {
                Index:      0,
                Name:       "Inp1",
                UploadName: "Inp1",
                Label:      "第1路脉冲常数",
                Type:       2,
                Decimals:   2,
                Unit:       "",
                Params: Params{
                    Min:            "",
                    Max:            "",
                    MinMaxAlarm:    false,
                    Step:           "",
                    StepAlarm:      false,
                    DataLength:     "",
                    DataLengthAlarm: false,
                    StartTime:      0,
                    Duration:       0,
                },
            },
            "Inp2": {
                Index:      1,
                Name:       "Inp2",
                UploadName: "Inp2",
                Label:      "第2路脉冲常数",
                Type:       2,
                Decimals:   2,
                Unit:       "",
                Params: Params{
                    Min:            "",
                    Max:            "",
                    MinMaxAlarm:    false,
                    Step:           "",
                    StepAlarm:      false,
                    DataLength:     "",
                    DataLengthAlarm: false,
                    StartTime:      0,
                    Duration:       0,
                },
            },
        },
    }

    // 保存模型
    if err := saveModel(db, exampleModel.Name, exampleModel); err != nil {
        log.Fatalf("保存模型失败: %v", err)
    }

    // 查询模型
    model, err := getModel(db, "电表模型")
    if err != nil {
        log.Fatalf("查询模型失败: %v", err)
    }
    fmt.Printf("查询到的模型: %+v\n", model)


    // 查询所有模型
    allModels, err := listAllModels(db)
    if err != nil {
        log.Fatalf("查询所有模型失败: %v", err)
    }
    fmt.Printf("所有模型数据: %+v\n", allModels)

//
    Update(db) 
}


